/**
 * 补齐各个 POSIX 系统的 API 差异
 * 张勇 41204@qq.com
 */

#ifdef _WIN32
	#define _CRT_SECURE_NO_WARNINGS
	#include <windows.h>
    #include <minwindef.h>
    #include <debugapi.h>
	#include <time.h>       // for time(), CLOCK_REALTIME
#elif (defined USE_MICROLIB)
	#include <string.h>
#else
    // _GNU_SOURCE 应在 unistd.h 前定义
	#ifndef _GNU_SOURCE
    	#define _GNU_SOURCE
	#endif
	#include <strings.h>    // for strcasecmp()
	#include <string.h>
	#include <libgen.h>     // for basename(), dirname()
	#include <time.h>
#endif

#include "unios.h"
#include "posix_patch.h"

#if (defined _MSC_VER) || (defined USE_MICROLIB)

const char* memmem(const char* haystack, size_t hlen, const char* needle, size_t nlen) {
    if (!haystack || !needle || nlen <= 1) return NULL;
    const char* cur;
    const char* last;
    last = haystack + hlen - nlen;
    for (cur = haystack; cur <= last; ++cur) {
        if (cur[0] == needle[0] && memcmp(cur, needle, nlen) == 0) {
            return cur;
        }
    }
    return NULL;
}

#else

void _splitpath(const char *_path, char *drive, char *dir, char *fname, char *ext) {
    if(drive) *drive = '\0';

    char path[256];
    strncpy(path, _path, sizeof(path)-1);
    const char *name = basename(path);
    if(dir) strncpy(dir, dirname(path), 256);

    if(fname || ext) {
        const char *dot = strrchr(name, '.');
        if(dot) {
            if(fname) strncpy(fname, name, dot-name);
            if(ext) strncpy(ext, dot, 256);
        } else {
            if(fname) strncpy(fname, name, 256);
            if(ext) *ext = '\0';
        }
    }
}

int stricmp(const char *s1, const char *s2) {
    return strcasecmp(s1, s2);
}

#if !defined(__linux__) && !defined(__unix__)

// Vitis 中 string.h 和 libgen.h 虽然声明了 basename(), dirname()，但是没有实现？

char* basename(char *path) {
    char *base = strrchr(path, '/');
    return base ? base + 1 : path;
}

char *dirname(char *path) {
    char *last_slash = strrchr(path, '/');
    if (last_slash != NULL) {
        *last_slash = '\0';  // 截断到最后一个 '/'
        return path;
    }
    return ".";  // 无斜杠，返回当前目录
}

// _gettimeofday()
int _gettimeofday(struct timeval *tv, void *tzvp) {
    tv->tv_sec = unios_rtcsec_get();
    tv->tv_usec = unios_us_now() % 1000000;  // get remaining microseconds
    return 0;  // return non-zero for error
}

#endif

#endif
